import java.util.*;

public class Calculations
{
	//Singleton
	Enroll e=null;
	
	private static Calculations calculations=null;
	private Calculations()
	{}
	public static Calculations getInstance()
	{
		if(calculations==null)
		{
			calculations = new Calculations();
		}
		return calculations;
	}
	//
	
	public double calculateFinalMark(Enroll en)
	{
		e=null;
		System.gc();
		e=en;
		en=null;
		Course c=XmlOperations.getInstance().searchCourseByNo(Integer.toString(e.getCode()));
		double fm=0;
		
		if(c.getType()==ProgramUitl.COURSE_TYPE.CORE || c.getType()==ProgramUitl.COURSE_TYPE.OPTIONAL)
		{
			float assignment1,assignment2,assignment3,classTest,practical,finalPaper;			
		
			if(e.getMarksAssignment1Repeat()!=ProgramUitl.MIN_MARKS)
			{
				assignment1=e.getMarksAssignment1Repeat();
			}
			else
			{
				assignment1=e.getMarksAssignment1();
			}
			
			if(e.getMarksAssignment2Repeat()!=ProgramUitl.MIN_MARKS)
			{
				assignment2=e.getMarksAssignment2Repeat();
			}
			else
			{
				assignment2=e.getMarksAssignment2();
			}

			if(e.getMarksAssignment3Repeat()!=ProgramUitl.MIN_MARKS)
			{
				assignment3=e.getMarksAssignment3Repeat();
			}
			else
			{
				assignment3=e.getMarksAssignment3();
			}

			if(e.getMarksClassTestRepeat()!=ProgramUitl.MIN_MARKS)
			{
				classTest=e.getMarksClassTestRepeat();
			}
			else
			{
				classTest=e.getMarksClassTest();
			}

			if(e.getMarksPracticalRepeat()!=ProgramUitl.MIN_MARKS)
			{
				practical=e.getMarksPracticalRepeat();
			}
			else
			{
				practical=e.getMarksPractical();
			}			
			
			if(e.getMarksFinalPaperRepeat()!=ProgramUitl.MIN_MARKS)
			{
				finalPaper=e.getMarksFinalPaperRepeat();
			}
			else
			{
				finalPaper=e.getMarksFinalPaper();
			}
			
			if(c.getType()==ProgramUitl.COURSE_TYPE.CORE)
			{
								
				if(c.getHasPracticals())
				{
					fm= Math.ceil((double) ((assignment1 * 0.05 ) + (assignment2 * 0.05) + (assignment3 * 0.1) + ( classTest * 0.2 ) + (practical * 0.2) + (finalPaper * 0.4 )));
						
				}
				else
				{
					fm= Math.ceil((double) ((assignment1 * 0.05 ) + (assignment2 * 0.05) + (assignment3 * 0.1) + ( classTest * 0.3 ) + (finalPaper * 0.5 )));
				}
			}
			else
			{
				if(c.getHasPracticals())
				{
					fm= Math.ceil((double) ((assignment1 * 0.05 ) + (assignment2 * 0.1) +  ( classTest * 0.25 ) + (practical * 0.2) + (finalPaper * 0.4 )));
						
				}
				else
				{
					fm= Math.ceil((double) ((assignment1 * 0.05 ) + (assignment2 * 0.1) +  ( classTest * 0.25 ) + (finalPaper * 0.6 )));
				}				
			}
			
			
		}
		else
		{
			float ir,ip,fr,fp,fpr;
			
			if(e.getMarksInterimReportRepeat()!=ProgramUitl.MIN_MARKS)
			{
				ir=e.getMarksInterimReportRepeat();
			}
			else
			{
				ir=e.getMarksInterimReport();
			}
			
			if(e.getMarksInterimPresentationRepeat()!=ProgramUitl.MIN_MARKS)
			{
				ip=e.getMarksInterimPresentationRepeat();
			}
			else
			{
				ip=e.getMarksInterimPresentation();
			}
			
			if(e.getMarksFinalReportRepeat()!=ProgramUitl.MIN_MARKS)
			{
				fr=e.getMarksFinalReportRepeat();
			}
			else
			{
				fr=e.getMarksFinalReport();
			}
			
			if(e.getMarksFinalPresentationRepeat()!=ProgramUitl.MIN_MARKS)
			{
				fp=e.getMarksFinalPresentationRepeat();
			}
			else
			{
				fp=e.getMarksFinalPresentation();
			}
			
			if(e.getMarksFinalProductRepeat()!=ProgramUitl.MIN_MARKS)
			{
				fpr=e.getMarksFinalProductRepeat();
			}
			else
			{
				fpr=e.getMarksFinalProduct();
			}	
			
			fm= Math.ceil((double) ((ir * 0.1 ) + (ip * 0.1) +  ( fr * 0.2 ) + (fp * 0.4 )+ (fpr * 0.2 )));
		}
		
		return fm;
	}

	public String calculateFinalGrade(Enroll en)
	{
		
		e=null;
		System.gc();
		e=en;
		en=null;
		
		if(e.getFinalMark() >=85)
		{
			return ProgramUitl.GRADE_A_P_TEXT;
		}
		else if(e.getFinalMark() >=75)
		{
			return ProgramUitl.GRADE_A_TEXT;
		}
		else if(e.getFinalMark() >=70)
		{
			return ProgramUitl.GRADE_A_M_TEXT;
		}		
		else if(e.getFinalMark() >=65)
		{
			return ProgramUitl.GRADE_B_P_TEXT;
		}
		else if(e.getFinalMark() >=60)
		{
			return ProgramUitl.GRADE_B_TEXT;
		}	
		else if(e.getFinalMark() >=55)
		{
			return ProgramUitl.GRADE_B_M_TEXT;
		}		
		else if(e.getFinalMark() >=50)
		{
			return ProgramUitl.GRADE_C_TEXT;
		}
		else if(e.getFinalMark() >=25)
		{
			return ProgramUitl.GRADE_D_TEXT;
		}
		else
		{
			return ProgramUitl.GRADE_E_TEXT;
		}
	}
	
	public float calculateFinalGP(Enroll en)
	{
		
		e=null;
		System.gc();
		e=en;
		en=null;
		
		if(e.getFinalMark() >=85)
		{
			return ProgramUitl.GRADE_A_P_GP;
		}
		else if(e.getFinalMark() >=75)
		{
			return ProgramUitl.GRADE_A_GP;
		}
		else if(e.getFinalMark() >=70)
		{
			return ProgramUitl.GRADE_A_M_GP;
		}		
		else if(e.getFinalMark() >=65)
		{
			return ProgramUitl.GRADE_B_P_GP;
		}
		else if(e.getFinalMark() >=60)
		{
			return ProgramUitl.GRADE_B_GP;
		}	
		else if(e.getFinalMark() >=55)
		{
			return ProgramUitl.GRADE_B_M_GP;
		}		
		else if(e.getFinalMark() >=50)
		{
			return ProgramUitl.GRADE_C_GP;
		}
		else if(e.getFinalMark() >=25)
		{
			return ProgramUitl.GRADE_D_GP;
		}
		else
		{
			return ProgramUitl.GRADE_E_GP;
		}		
	}

	public float calculateGPA(List<Enroll> el)
	{	
		float sumCreadits=0.0F;
		float sumCreatitsIntoGP=0.0F;
		if(el==null)
		{
			return 0.0F;
		}
		else
		{
			for (int i = 0; i < el.size(); i++) 
			{				
				Enroll eTmp=(Enroll)el.get(i);
				Course c=XmlOperations.getInstance().searchCourseByNo(Integer.toString(eTmp.getCode()));
				
				sumCreatitsIntoGP+=(float)(c.getCredits() * eTmp.getFinalGP());
				sumCreadits+=(float)c.getCredits();
			}

			if(sumCreadits==0.0F || sumCreatitsIntoGP==0.0F)
			{	
				return 0.0F;
			}
			else
			{
				return sumCreatitsIntoGP/sumCreadits;
			}
		}
	}

	public String calculateClass(float gpa)
	{
		if(gpa >= ProgramUitl.GPA_FIRST)
		{
			return ProgramUitl.CLASS_FIRST;
		}
		else if(gpa >= ProgramUitl.GPA_SECOND_UPPER)
		{
			return ProgramUitl.CLASS_SECOND_UPPER;
		}
		else if(gpa >= ProgramUitl.GPA_SECOND_LOWER)
		{
			return ProgramUitl.CLASS_SECOND_LOWER;
		}
		else if(gpa >= ProgramUitl.GPA_NORMAL)
		{
			return ProgramUitl.CLASS_NORMAL;
		}
		else
		{
			return ProgramUitl.CLASS_FAIL;
		}		
	}
}